package com.kg.tombs.db;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.mongo.BulkOperation;
import io.vertx.ext.mongo.MongoClient;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
public class MongoVerticle extends AbstractVerticle {


    private static final String DATABASE_HOST = "localhost";
    private static final int DATABASE_PORT = 27017;
    private static final String DATABASE_NAME = "tombs_db";
    private static final String DATABASE_USERNAME = "root";
    private static final String DATABASE_PASSWORD = "123qweasdzxc";

    private MongoClient client;

    @Override
    public void start(Promise<Void> startPromise) throws Exception {
        JsonObject mongoConfig = new JsonObject()
                .put("connection_string", "mongodb://" + DATABASE_USERNAME + ":" + DATABASE_PASSWORD +
                        "@" + DATABASE_HOST + ":" + DATABASE_PORT + "/" + DATABASE_NAME + "?authSource=admin")
                .put("db_name", DATABASE_NAME);
        client = MongoClient.create(vertx, mongoConfig);
        client.runCommand("ping", new JsonObject().put("ping", 1))
                .onSuccess(result -> startPromise.complete())
                .onFailure(startPromise::fail);
    }

    /**
     * 插入文档
     * @param collection 集合名称
     * @param document 要插入的文档
     * @return 插入结果的Future
     */
    public Future<JsonObject> insert(String collection, JsonObject document) {
        Promise<JsonObject> promise = Promise.promise();

        client.insert(collection, document)
                .onSuccess(id -> {
                    JsonObject result = new JsonObject().put("id", id);
                    promise.complete(result);
                })
                .onFailure(promise::fail);

        return promise.future();
    }

    /**
     * 查询文档
     * @param collection 集合名称
     * @param query 查询条件
     * @return 查询结果的Future
     */
    public Future<JsonObject> findOne(String collection, JsonObject query) {
        Promise<JsonObject> promise = Promise.promise();

        client.findOne(collection, query, null)
                .onSuccess(result -> {
                    if (result == null) {
                        promise.complete(new JsonObject());
                    } else {
                        promise.complete(result);
                    }
                })
                .onFailure(promise::fail);

        return promise.future();
    }

    /**
     * 获取数据库中所有集合的列表
     * @return 包含集合名称列表的Future
     */
    public Future<JsonObject> listCollections() {
        Promise<JsonObject> promise = Promise.promise();

        client.getCollections()
                .onSuccess(collections -> {
                    JsonObject result = new JsonObject().put("collections", collections);
                    promise.complete(result);
                })
                .onFailure(promise::fail);

        return promise.future();
    }

    /**
     * 查询多个文档
     * @param collection 集合名称
     * @param query 查询条件
     * @return 查询结果的Future
     */
    public Future<List<JsonObject>> find(String collection, JsonObject query) {
        Promise<List<JsonObject>> promise = Promise.promise();
        client.find(collection, query)
                .onSuccess(promise::complete)
                .onFailure(promise::fail);
        return promise.future();
    }

    /**
     * 更新文档
     * @param collection 集合名称
     * @param query 查询条件
     * @param update 更新内容
     * @return 更新结果的Future
     */
    public Future<JsonObject> update(String collection, JsonObject query, JsonObject update) {
        Promise<JsonObject> promise = Promise.promise();

        client.updateCollection(collection, query, new JsonObject().put("$set", update))
                .onSuccess(updateResult -> {
                    JsonObject result = new JsonObject()
                            .put("matched", updateResult.getDocMatched())
                            .put("modified", updateResult.getDocModified());
                    promise.complete(result);
                })
                .onFailure(promise::fail);

        return promise.future();
    }

    /**
     * 删除文档
     * @param collection 集合名称
     * @param query 删除条件
     * @return 删除结果的Future
     */
    public Future<JsonObject> delete(String collection, JsonObject query) {
        Promise<JsonObject> promise = Promise.promise();

        client.removeDocuments(collection, query)
                .onSuccess(deleteResult -> {
                    JsonObject result = new JsonObject()
                            .put("deleted", deleteResult.getRemovedCount());
                    promise.complete(result);
                })
                .onFailure(promise::fail);

        return promise.future();
    }

    /**
     * 批量插入文档
     *
     * @param collection 集合名称
     * @param documents  要插入的文档列表
     */
    public void insertMany(String collection, List<JsonObject> documents) {
        Promise<JsonObject> promise = Promise.promise();

        // 创建批量写入选项
        List<BulkOperation> operations = documents.stream()
                .map(BulkOperation::createInsert)
                .collect(Collectors.toList());

        client.bulkWrite(collection, operations)
                .onSuccess(bulkResult -> {
                    JsonObject result = new JsonObject()
                            .put("insertedCount", bulkResult.getInsertedCount());
                    promise.complete(result);
                })
                .onFailure(promise::fail);

        promise.future();
    }

    /**
     * 删除集合
     *
     * @param collection 集合名称
     */
    public void dropCollection(String collection) {
        Promise<JsonObject> promise = Promise.promise();

        client.dropCollection(collection)
                .onSuccess(v -> promise.complete(new JsonObject().put("dropped", true)))
                .onFailure(promise::fail);

        promise.future();
    }



    /**
     * 关闭客户端连接
     * @param stopPromise 停止Future
     * @throws Exception 停止异常
     */
    @Override
    public void stop(Promise<Void> stopPromise) throws Exception {
        if (client != null) {
            client.close();
        }
        stopPromise.complete();
    }

}
